local _M = { _VERSION = "0.1" }

local jwt        = require "resty.jwt"
local validators = require "resty.jwt-validators"
      validators.set_system_leeway(0)

local JWT_SECRET            = "MUSE_GAAS_RESTY_JWT"
local JWT_HEADER            = { typ="JWT", alg="HS256" }
local JWT_EXPIRATION_FIELDS = { "nbf", "exp" }
local ERR = {
  INVALID_TOKEN = "INVALID_TOKEN",
}

do
  function _M.pack( payload, header )
    assert(payload ~= nil, "invalid argument 'payload'")

    local jwt_token = jwt:sign(
      JWT_SECRET,
      {
        header  = header or JWT_HEADER,
        payload = payload
      }
    )

    return jwt_token
  end


  function _M.unpack( token )
    assert(type(token)=="string", "invalid argument 'token'")

    local reply = jwt:verify(
      JWT_SECRET,
      token,
      {
        __jwt = validators.require_one_of(JWT_EXPIRATION_FIELDS),
        nbf = validators.opt_is_not_before(),
        exp = validators.opt_is_not_expired()
      }
    )

    if not reply.valid then
      return nil, ERR.INVALID_TOKEN
    end

    return {
      verified = reply.verified,
      reason   = reply.reason,
      header   = reply.header,
      payload  = reply.payload,
    }
  end
end


-- Ticket
do
  local TICKET = {}
  local TICKET_mt = {__index = TICKET}

  function TICKET.new(v)
    assert(type(v)=="table", "invalid argument 'ticket'")

    return setmetatable({
      header  = v.header,
      payload = v.payload,
    }, TICKET_mt)
  end


  function TICKET.renew(self, timestamp, ttl)
    assert(self ~= nil, "invalid argument 'self'")

    timestamp = timestamp  or  ngx.time()
    ttl       = ttl        or  self.payload.ttl

    self.payload.ttl = ttl
    self.payload.exp = timestamp + ttl

    return self
  end


  function TICKET.pack(self)
    assert(self ~= nil, "invalid argument 'self'")

    return _M.pack(self.payload, self.header)
  end

  -- export
  _M.ticket = TICKET
end


return _M
